Skip to content

feat: add trezor onchain event watcher#976

Merged
ovitrif merged 15 commits into
masterfrom
feat/onchain-event-watcher
Jun 8, 2026
Merged

feat: add trezor onchain event watcher#976
ovitrif merged 15 commits into
masterfrom
feat/onchain-event-watcher

Conversation

@coreyphillips

@coreyphillips coreyphillips commented May 29, 2026

Copy link
Copy Markdown
Contributor

Adds an Event Watcher section to the (dev-only) Trezor screen that consumes the new bitkit-core on-chain xpub watcher. Enter or populate an extended key, start/stop a live watcher, and observe streaming balance, transactions, connection status, and an event log.

Depends on bitkit-core 0.1.65

Description

  • New WatcherSection composable: extended-key + gap-limit inputs, populate-from-xpub, start/stop controls, and a live view of balance, transactions, connection status, and an event log.
  • TrezorViewModel:
    • Collects WatcherEvents from the repo and maps them into a new TrezorWatcherState (balance, transactions, tx count, block height, account type, connection status, event log).
    • Generates a per-session watcherId, validates the xpub/gap-limit inputs, and surfaces errors via toasts.
    • Stops the active watcher in onCleared() so no watcher thread is leaked.
  • TrezorRepo: exposes a buffered watcherEvents SharedFlow bridged from a core EventListener, plus startWatcher / stopWatcher / stopAllWatchers returning Result<Unit>.
  • TrezorService: thin wrappers over onchainStartWatcher / onchainStopWatcher / onchainStopAllWatchers.
  • Bumped bitkit-core to 0.1.65 in libs.versions.toml.

QA Notes

  • Build resolves bitkit-core 0.1.65.
  • Dev Settings → Trezor → Event Watcher:
    • Populate from xpub (or paste an extended key), set a gap limit, and start the watcher; confirm status goes STARTING → CONNECTED and the initial balance/transactions populate.
    • Send a tx to the watched xpub and confirm the balance/tx list and event log update live.
    • Drop the network and confirm DISCONNECTED → CONNECTED transitions with a "Reconnected" log entry.
    • Stop the watcher and confirm state clears; leave/return to the screen and confirm no leaked watcher (stops on onCleared).
    • Invalid input (blank key, non-numeric gap limit) shows an error toast and does not start a watcher.
  • Tests run: ./gradlew compileDevDebugKotlin, ./gradlew testDevDebugUnitTest --tests TrezorViewModelTest --tests TrezorRepoTest, ./gradlew detekt — all pass.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b4fd96a304

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread app/src/main/java/to/bitkit/ui/screens/trezor/TrezorViewModel.kt Outdated

@ovitrif ovitrif left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM with one nit

Comment thread app/src/main/java/to/bitkit/repositories/TrezorRepo.kt Outdated
@coreyphillips coreyphillips requested a review from ovitrif June 2, 2026 15:15
@ovitrif ovitrif added this to the 2.3.0 milestone Jun 3, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 018feaca8b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread app/src/main/java/to/bitkit/ui/screens/trezor/TrezorViewModel.kt

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 58f11e5f04

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread app/src/main/java/to/bitkit/ui/screens/trezor/TrezorViewModel.kt
@piotr-iohk piotr-iohk modified the milestones: 2.3.0, 2.4.0 Jun 5, 2026
@jvsena42

jvsena42 commented Jun 8, 2026

Copy link
Copy Markdown
Member

Synced with master to fix the pipe

@jvsena42

jvsena42 commented Jun 8, 2026

Copy link
Copy Markdown
Member

Watcher account-type detection can't reach TAPROOT

While reviewing the watcher flow I traced how the Account Type row (WatcherSection.kt:160) is populated. The value comes from bitkit-core via WatcherEvent.TransactionsChanged.accountType, and bitkit-core auto-detects the type purely from the extended-key SLIP-132 prefix:

Prefix (main/test) AccountType
xpub/tpub LEGACY (P2PKH)
ypub/upub WRAPPED_SEGWIT (P2SH-P2WPKH)
zpub/vpub NATIVE_SEGWIT (P2WPKH)

This mapping is correct per SLIP-132. The catch: BIP86 taproot has no dedicated prefix — taproot accounts are serialized as plain xpub/tpub. So prefix auto-detection can never yield TAPROOT; a taproot key gets classified as LEGACY and watched as P2PKH (wrong address set), with no xpub-form prefix the user could supply to correct it.

bitkit-core already anticipates this — WatcherParams.accountType is a nullable override ("auto-detected from key prefix if None"). But TrezorRepo.startWatcher (TrezorRepo.kt:587) hardcodes accountType = null and doesn't accept an account-type argument, so the override is never reachable from this screen.

Same class of issue affects a native-segwit account exported in tpub form (instead of vpub): it silently watches the legacy address set.

Suggestion (optional, can be a follow-up): thread an AccountType? through startWatcherWatcherParams.accountType and add a selector in WatcherSection (defaulting to prefix auto-detect). That makes taproot watchable and lets users override a misleading prefix.

Not blocking — flagging since the TAPROOT enum value is currently unreachable through the watcher UI.


Test vectors for reviewing the watcher

Mnemonic (test only, do not fund):

borrow shove play liberty someone menu acquire sauce damp hockey same ivory

Account-level extended keys (m/purpose'/coin'/0'), correctly prefixed per SLIP-132. Paste each into the watcher and confirm the detected Account Type:

Account type Path Mainnet Testnet/Regtest
LEGACY (P2PKH) m/44'/x'/0' xpub6CdEcqzgLUGihHjVHLDdGpA39E5L3PSHau15T22nbS9Tknc6Ea9qeDcacD6hgJwC5h3oFA1XjrZSZNxqCAhTLLEUUubr1DTAkKXLjZK4n1E tpubDDmDh7gnRQvgFAy9iUYaqxp2ga7127uq3Dm4Ty2BLWfGzf1wE6wpMszUY7gVrHuTC1ipyW3gsrscxBy4JQo4cyBaWcaTqHk7y5BgK1LZpDr
WRAPPED_SEGWIT (P2SH-P2WPKH) m/49'/x'/0' ypub6YGWPzNgmgu73wbNyzLm2pzkVyQnJuvEJvWPaFBNxfK16TCYd5Dveq6n4k74Zigo3mLXi2ZPoDeuMfpvWc6HFXsdobr7P1S3kVr2WXDSMA3 upub5EvnSNaUQddSNvdQwr6Dr52rSgMQtCNe2r5rABFaYyPJyruwAZZgreeaeqFGb9aD5Bk1f8odQDxiqLF8byb7mSf5xnQU3Af6xmcHJ3tR8Ro
NATIVE_SEGWIT (P2WPKH) m/84'/x'/0' zpub6rvr6fTP1a9gwtMfGaYUMr3criSK8hHysUVk4SGKiBvyPuZyhTik5ytLGVVMjxxH1kbDdx7KQwKL91RYdhVABWzxbYkco1beZaJXtYBvCs3 vpub5ZY7nEBNhdQSwomKbQfTzZmHm7GgzNRV9v6T2j1FKJt77VvXWTxgN4yth6puqNSKK8JQdF2NCNgX75P9C1EzeSToYYMQbXtSqXSHR4KZX9Q
TAPROOT (P2TR)¹ m/86'/x'/0' xpub6CETgoWxHvvPjmYAcw1WJjeqsZjZEXgZw1qc8ci9KkwUZ8HZTKsqxLvg13aFxegkpJ3gvBFCroeP486xuE5SGuRsnnrnhof1qcECBZKvS4s tpubDCzdfosztoepoTNmpiR7XbA9Wd67m8VDgsjiEeZcqjqZTa9eySaGCQTn4Z7JRkZ6qgnbHQvtsuYVqhqbTaKQPo3iAGXmWbUCMh4GSFkXMAS

x' = 0' for mainnet, 1' for testnet/regtest.

¹ The taproot keys carry the xpub/tpub prefix (no BIP86-specific version bytes exist), so they will currently be detected as LEGACY — that's the gap described above.

Screen_recording_20260608_091038.webm

jvsena42
jvsena42 previously approved these changes Jun 8, 2026

@jvsena42 jvsena42 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aproved with one follow-up comment #976 (comment)

@coreyphillips

Copy link
Copy Markdown
Contributor Author

Aproved with one follow-up comment #976 (comment)

Addressed in this commit.

@jvsena42 jvsena42 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After 12b210a the app detects new events, but still displays zero for transaction history fields

Screen_recording_20260608_102111.webm

@coreyphillips

Copy link
Copy Markdown
Contributor Author

After 12b210a the app detects new events, but still displays zero for transaction history fields

Extended the account type selector to lookups as of this commit.

@coreyphillips coreyphillips requested a review from jvsena42 June 8, 2026 14:39
@ovitrif ovitrif dismissed jvsena42’s stale review June 8, 2026 19:22

already addressed change request/

@ovitrif ovitrif left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tAck

Tested on my Pixel 10 Android phone with my Trezor Safe 7 test device. I verified the dev-only Trezor Event Watcher flow end to end: connected the device, populated/used the xpub, started and stopped the watcher, and confirmed balance/transaction updates plus event log behavior worked as expected as I sent funds to a trezor device address then mined on regtest to see funds confirm.

Also validated network OFF + re-ON responsivity of the watcher on UI and in logic.

@ovitrif

ovitrif commented Jun 8, 2026

Copy link
Copy Markdown
Collaborator

Additional Taproot/regtest coverage:

Verified Joao’s account-type override case with Safe 7. Used a Bitcoin Testnet Taproot tpub (m/86'/1'/0') in Bitkit on REGTEST with account type Taproot, funded a derived bcrt1p... address, saw the watcher update while pending, then saw it update again as confirmed after mining. Account type displayed TAPROOT; balance, tx list/count, block height, and event log looked correct.

scrcpy.2026-06-08.006606.mp4

@ovitrif ovitrif merged commit dd291ac into master Jun 8, 2026
17 checks passed
@ovitrif ovitrif deleted the feat/onchain-event-watcher branch June 8, 2026 19:56
@ovitrif ovitrif mentioned this pull request Jun 9, 2026
7 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants